package cn.virens.web.controller.weixin;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.hutool.core.util.StrUtil;
import cn.virens.common.CloseableUtil;
import cn.virens.common.RequestUtil;
import cn.virens.exception.APIException;
import cn.virens.exception.ExceptionUtil;
import cn.virens.web.common.BaseJSONController;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;

@Controller
@RequestMapping("wx")
public class WxMpContorller extends BaseJSONController {
	private @Autowired WxMpMessageRouter mWxMpMessageRouter;
	private @Autowired WxMpConfigStorage mWxMpConfigStorage;
	private @Autowired WxMpService mWxMpService;

	@RequestMapping(value = "mp")
	public void mp(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String nonce = RequestUtil.getValueStr(request, "nonce");
		String signature = RequestUtil.getValueStr(request, "signature");
		String timestamp = RequestUtil.getValueStr(request, "timestamp");

		response.setContentType("text/html;charset=utf-8");
		response.setStatus(HttpServletResponse.SC_OK);

		InputStream inputStream = null;
		PrintWriter printWriter = null;

		String encryptType = null;
		String msgSignature = null;
		WxMpXmlMessage inMessage = null;
		WxMpXmlOutMessage outMessage = null;
		try {
			printWriter = response.getWriter();

			// 检查消息签名是否正确
			if (mWxMpService.checkSignature(timestamp, nonce, signature) == true) {
				String echostr = RequestUtil.getValueStr(request, "echostr");

				if (StringUtils.isEmpty(echostr)) {
					inputStream = request.getInputStream();
					encryptType = RequestUtil.getValueStr(request, "encrypt_type", "raw");
					msgSignature = RequestUtil.getValueStr(request, "msg_signature", null);

					// 转换消息为明文
					if (StrUtil.equals(encryptType, "raw")) {
						inMessage = WxMpXmlMessage.fromXml(inputStream);
					} else if (StrUtil.equals(encryptType, "aes")) {
						inMessage = WxMpXmlMessage.fromEncryptedXml(inputStream, mWxMpConfigStorage, timestamp, nonce, msgSignature);
					} else {
						throw new APIException("Error", "不可识别的加密类型");
					}

					// 经消息路由处理消息,响应消息
					if ((outMessage = mWxMpMessageRouter.route(inMessage)) == null) {
						printWriter.println("SUCCESS");
					} else if (StrUtil.equals(encryptType, "raw")) {
						printWriter.println(outMessage.toXml());
					} else if (StrUtil.equals(encryptType, "aes")) {
						printWriter.println(outMessage.toEncryptedXml(mWxMpConfigStorage));
					} else {
						logger.debug("未知加密类型");
					}
				} else {
					printWriter.println(echostr);
				}
			} else {
				printWriter.println("非法请求");
			}
		} catch (Exception e) {
			logger.error("微信消息错误：" + ExceptionUtil.getCode(e));
			logger.error("微信消息错误：" + ExceptionUtil.getMessage(e));
			e.printStackTrace();
			printWriter.println(ExceptionUtil.getMessage(e));
		} finally {
			CloseableUtil.close(inputStream);
			CloseableUtil.close(printWriter);
		}
	}
}
